package com.hunan.api.catv.service.biz.wx;

import cn.hutool.core.lang.UUID;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.gson.JsonObject;
import com.hunan.api.catv.common.CacheName;
import com.hunan.api.catv.common.Constants;
import com.hunan.api.catv.common.ConstantsMsg;
import com.hunan.api.catv.entity.ServiceResult;
import com.hunan.api.catv.entity.po.Member;
import com.hunan.api.catv.entity.vo.MemberVo;
import com.hunan.api.catv.entity.vo.SimpleMemberVo;
import com.hunan.api.catv.service.ResultService;
import com.hunan.api.catv.service.biz.cache.CacheBiz;
import com.hunan.api.catv.service.biz.member.MemberBiz;
import com.hunan.api.catv.service.impl.member.MemberService;
import com.hunan.api.catv.service.impl.wx.WxService;
import com.hunan.api.catv.utils.GsonUtils;
import com.hunan.api.catv.utils.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;

@Service
public class WxBiz extends ResultService {


    @Autowired
    RedisUtils redisUtils;

    @Autowired
    WxService wxLoginService;

    @Autowired
    CacheBiz cacheBiz;

    @Value("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}")
    String webAccessTokenUrl;
    @Value("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi")
    String ticketUrl;

    @Autowired
    MemberService memberService;

    @Autowired
    private MemberBiz memberbiz;

    public ServiceResult getAccessToken(String code) {
        JsonObject wxCofig = GsonUtils.fromJson(cacheBiz.getSystemDict(Constants.wx_conf), JsonObject.class);
        if (!ObjectUtils.isEmpty(wxCofig)) {
            String appid = wxCofig.get("AppID").getAsString();
            String secret = wxCofig.get("secret").getAsString();
            String domain = wxCofig.get("domain").getAsString();
            JsonObject result = wxLoginService.getAccessToken(domain, appid, secret, code);
            if (!ObjectUtils.isEmpty(result) && !ObjectUtils.isEmpty(result.get("access_token")) && !ObjectUtils.isEmpty(result.get("openid"))) {
                return buildOK(result, "");
            }
            String msg = result.get("errmsg").getAsString();
            log.error("[MemberConf-Error: {}]", msg);
        }
        return buildFail(ConstantsMsg.wx_getToken_fail);
    }

    public ServiceResult getUserInfo(String accessToken, String openid) {
        JsonObject wxCofig = GsonUtils.fromJson(cacheBiz.getSystemDict(Constants.wx_conf), JsonObject.class);
        if (!ObjectUtils.isEmpty(wxCofig)) {
            String domain = wxCofig.get("domain").getAsString();
            JsonObject result = wxLoginService.getUserinfo(domain, accessToken, openid);
            if (!ObjectUtils.isEmpty(result) && !ObjectUtils.isEmpty(result.get("openid"))) {
                return buildOK(result, "");
            }
            String msg = result.get("errmsg").getAsString();
            log.error("[MemberConf-Error: {}]", msg);
        }
        return buildFail(ConstantsMsg.getUserInfo_fail);
    }

    public Object webAuthorization(String code) {
        log.info("网页授权接口：{}", code);
        JsonObject wxCofig = GsonUtils.fromJson(cacheBiz.getSystemDict(Constants.wx_web_conf), JsonObject.class);
        JsonObject result = new JsonObject();
        if (!ObjectUtils.isEmpty(wxCofig)) {
            String appid = wxCofig.get("AppID").getAsString();
            String secret = wxCofig.get("secret").getAsString();
            String domain = wxCofig.get("domain").getAsString();
            JsonObject wxResult = wxLoginService.getAccessToken(domain, appid, secret, code);
            if (!ObjectUtils.isEmpty(wxResult) && !ObjectUtils.isEmpty(wxResult.get("access_token")) && !ObjectUtils.isEmpty(wxResult.get("unionid"))) {
                String unionid = wxResult.get("unionid").getAsString();
                Member member = new Member();
                member.setWxUnionid(unionid);
                MemberVo memberVo = null;
                List<MemberVo> list = memberService.list(member);
                if (!ObjectUtils.isEmpty(list)) {
                    memberVo = list.get(0);
                }
                String ticket = UUID.fastUUID().toString(true);
                redisUtils.hset(CacheName.accessToken, unionid, wxResult.get("access_token").getAsString(), 7200);
                redisUtils.hset(CacheName.ticketToToken, ticket, unionid, 7200);
                if (memberVo != null) {
                    SimpleMemberVo sMemberVo = new SimpleMemberVo();
                    BeanUtils.copyProperties(memberVo, sMemberVo);
                    if (memberVo.getRegTime() != null) {
                        sMemberVo.setRegTime(memberVo.getRegTime().toLocalDateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    }
                    if (sMemberVo.getPhone() != null) {
                        sMemberVo.setPhone(sMemberVo.getPhone().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
                        result.add("auth", memberbiz.buildToken(memberVo.getMemberId()));
                    }
                    result.add("member", GsonUtils.fromJson(GsonUtils.toJson(sMemberVo), JsonObject.class));
                }
                result.addProperty("ticket", ticket);
                return buildOK(result);
            }
            String msg = wxResult.get("errmsg").getAsString();
            log.error("[MemberConf-Error: {}]", msg);
        }
        return buildFail(ConstantsMsg.wx_getToken_fail);
    }

    public Object webSign(String url, Integer memberId, String ticket) {
        log.info("JSSDK授权接口：{}-{}-{}", url, memberId, ticket);
        JSONObject result = new JSONObject();
        if (memberId == null) {
            Object hget = redisUtils.hget(CacheName.ticketToToken, ticket);
            if (!ObjectUtils.isEmpty(hget)) {
                Member member = new Member();
                member.setWxUnionid((String) hget);
                MemberVo memberVo = memberService.get(member);
                if (!ObjectUtils.isEmpty(memberVo)) {

                    memberId = memberVo.getMemberId();
                }
            }
        }
       /* if (memberId ==null) {
            return buildFail("用户未获取微信授权");
        }*/
        String wxTicket = (String) Optional.ofNullable(redisUtils.get(CacheName.tickets + memberId)).orElse("");
        if (StringUtils.isBlank(wxTicket)) {
//            MemberVo memberVo = memberService.getById(memberId);·
           /* if (ObjectUtils.isEmpty(memberVo) && ObjectUtils.isEmpty(memberVo.getWxUnionid())) {
                return buildFail("用户未获取微信授权");
            }
            Object accessToken = redisUtils.hget(CacheName.accessToken,memberVo.getWxUnionid());
            if (ObjectUtils.isEmpty(accessToken)) {
                return buildFail("微信授权已失效");
            }*/
            JsonObject wxCofig = GsonUtils.fromJson(cacheBiz.getSystemDict(Constants.wx_web_conf), JsonObject.class);
            Object accessToken = redisUtils.get("wx::jsAccessToken");
            if (ObjectUtils.isEmpty(accessToken) && !ObjectUtils.isEmpty(wxCofig)) {
                String appid = wxCofig.get("AppID").getAsString();
                String secret = wxCofig.get("secret").getAsString();
                String requestUrl = MessageFormat.format(webAccessTokenUrl, appid, secret);
                log.info("JSSKDK请求accessToken链接：{}", requestUrl);
                String s = HttpUtil.get(requestUrl);
                log.info("JSSKDK请求accessToken结果：{}", s);
                JSONObject jsonObject = JSONUtil.parseObj(s);
                accessToken = jsonObject.get("access_token");
                if (ObjectUtils.isEmpty(accessToken)) {
                    return buildFail("微信授权已失效");
                }
                redisUtils.set("wx::jsAccessToken", accessToken, jsonObject.getInt("expires_in"));
            }
            String requestUrl = MessageFormat.format(ticketUrl, accessToken);
            log.info("JSSKDK请求ticket链接：{}", requestUrl);
            String s = HttpUtil.get(requestUrl);
            log.info("JSSKDK请求ticket结果：{}", s);
            JSONObject jsonObject = JSONUtil.parseObj(s);

            if (jsonObject.get("errcode").equals(0)) {
                wxTicket = jsonObject.getStr("ticket");
                redisUtils.set(CacheName.tickets + memberId, wxTicket, (Integer) jsonObject.get("expires_in"));
            }
        }
        long timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        String noncestr = UUID.fastUUID().toString(true);
        try {
            url = URLDecoder.decode(url, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String concatStr = "jsapi_ticket=" + wxTicket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        log.info(concatStr);
        String serverSign = SecureUtil.sha1(concatStr);
        log.info(serverSign);
        result.set("timestamp", timestamp).set("nonceStr", noncestr).set("signature", serverSign);
        return result;
    }

    public Object webSign(String url) {
        log.info("JSSDK授权接口：{}", url);
        JSONObject result = new JSONObject();
        String wxTicket = (String) Optional.ofNullable(redisUtils.get(CacheName.tickets)).orElse("");
        if (StringUtils.isBlank(wxTicket)) {
            JsonObject wxCofig = GsonUtils.fromJson(cacheBiz.getSystemDict(Constants.wx_web_conf), JsonObject.class);
            Object accessToken = redisUtils.get("wx::jsAccessToken");
            if (ObjectUtils.isEmpty(accessToken) && !ObjectUtils.isEmpty(wxCofig)) {
                String appid = wxCofig.get("AppID").getAsString();
                String secret = wxCofig.get("secret").getAsString();
                String requestUrl = MessageFormat.format(webAccessTokenUrl, appid, secret);
                log.info("JSSKDK请求accessToken链接：{}", requestUrl);
                String s = HttpUtil.get(requestUrl);
                log.info("JSSKDK请求accessToken结果：{}", s);
                JSONObject jsonObject = JSONUtil.parseObj(s);
                accessToken = jsonObject.get("access_token");
                if (ObjectUtils.isEmpty(accessToken)) {
                    return buildFail("微信授权已失效");
                }
                redisUtils.set("wx::jsAccessToken", accessToken, jsonObject.getInt("expires_in"));
            }
            String requestUrl = MessageFormat.format(ticketUrl, accessToken);
            log.info("JSSKDK请求ticket链接：{}", requestUrl);
            String s = HttpUtil.get(requestUrl);
            log.info("JSSKDK请求ticket结果：{}", s);
            JSONObject jsonObject = JSONUtil.parseObj(s);

            if (jsonObject.get("errcode").equals(0)) {
                wxTicket = jsonObject.getStr("ticket");
                redisUtils.set(CacheName.tickets, wxTicket, (Integer) jsonObject.get("expires_in"));
            }
        }
        long timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        String noncestr = UUID.fastUUID().toString(true);
        try {
            url = URLDecoder.decode(url, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String concatStr = "jsapi_ticket=" + wxTicket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        log.info(concatStr);
        String serverSign = SecureUtil.sha1(concatStr);
        log.info(serverSign);
        result.set("timestamp", timestamp).set("nonceStr", noncestr).set("signature", serverSign);
        return result;
    }

    public static void main(String[] args) {
        String wxTicket = "LIKLckvwlJT9cWIhEQTwfFziQzGqCwGjdikXCu29xOX8iH524yNdxqbpn6WqF5CV03SjE28RXzVQRHtfGd17Zg";
        long timestamp = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        String noncestr = UUID.fastUUID().toString(true);
        String url = "http://localhost:8083/h5/red-film/f34e2fd87a1d4a3983c3af5a3cf25283";
        String concatStr = "jsapi_ticket=" + wxTicket + "&noncestr=" + noncestr + "&timestamp=" + timestamp + "&url=" + url;
        System.out.println(concatStr);
        String serverSign = SecureUtil.sha1(concatStr);

        System.out.println(serverSign);
    }

}
